/**
 * @description 腾讯语音服务
 * @doc https://cloud.tencent.com/document/product/1093/48982
 */
import SpeechRecognizer from './lib/speechrecognizer'
import WebRecorder from './lib/webrecorder'
import ConnService from './lib/conn-service'
import { signCallback, fitAsrText } from './lib/utils'
import { isEmptyQuote } from '@/utils'
import { EventNames, ErrorReport } from './index.d'

/**************** 默认配置 ****************/
export const defaultConfig = {
  origin: import.meta.env.XMOV_APP_XASR_ORIGIN,
  app_id: import.meta.env.XMOV_APP_XASR_APPID,
  secret_key: import.meta.env.XMOV_APP_XASR_SECRET_KEY,
  hotword_list: [],
  vad: 1000
}

export default class ASR {
  config = defaultConfig
  recognizer: SpeechRecognizer
  recorder: WebRecorder
  connService: ConnService

  results: LooseObject[] = []
  processText = ''

  private tag = '[::ASR::]'

  constructor(config?: any) {
    this.log(config)
    this.config = Object.assign({}, this.config, config)
    this.connService = new ConnService(defaultConfig)
  }

  private log(...messages) {
    console.log(this.tag, ...messages)
  }

  private error(...messages) {
    console.error(this.tag, ...messages)
  }

  private matchNativeError(error: DOMException) {
    let message: string
    const flat: string | number = error.name || error.code
    switch (flat) {
      case 'PERMISSION_DENIED':
      case 'PermissionDeniedError':
        message = '未获取到麦克风权限'
        break
      case 'NOT_SUPPORTED_ERROR':
      case 'NotSupportedError':
      case 'MANDATORY_UNSATISFIED_ERROR':
      case 'MandatoryUnsatisfiedError':
      case 'NotFoundError':
        message = '您的设备不支持录音'
        break
      default:
        message = '无法打开麦克风, 请重试'
        break
    }
    return message
  }

  private onError(error?: ErrorReport | DOMException, type?: string) {
    if (typeof error === 'string') {
      error = {
        message: error,
      }
    }
    if (type === 'native') {
      error = {
        ...error,
        message: this.matchNativeError(error as DOMException) || error.message,
      }
    }
    // this.closeInterval()
    this.stop()
  }

  private async getRecorder() {
    return new Promise((resolve, reject) => {
      this.recorder = new WebRecorder()
      if (isEmptyQuote(this.recorder)) {
        return reject({ toast: true, message: '语音识别还未准备好' })
      }
      this.recorder.OnReceivedData = (res: LooseObject) => {
        resolve(this.recorder)
        this.connService.sendBuffer(res)
      }
      this.recorder.OnError = (error: LooseObject) => {
        this.error('[recorder.OnError]', error)
        /**
         * 如果已获取录音权限，依然抛出`NotAllowedError`
         * 则为Safari禁止自动模仿音频错误
         * 可忽略
         */
        if (error?.name === 'NotAllowedError') return
        this.recorder.stop()
        this.error('[recorder.OnError]', error)
        this.onError(error, 'native')
      }
      this.recorder
        ?.start?.()
        .then(resolve)
        .catch((message: string) => {
          this.onError({
            message
          })
        })
    })
  }

  bindServiceEvent() {
    this.connService.onSocketOpen = this.onSocketOpen
    this.connService.onRecStart = this.onRecStart
    this.connService.onSentenceChange = this.onSentenceChange
    this.connService.onSentenceEnd = this.onSentenceEnd
    this.connService.onRecComplete = this.onRecComplete
    this.connService.onError = (res) => {
      this.onError(res)
    }
  }

  async start() {
    const socketState = this.connService.socket?.readyState
    if (socketState !== 1) {
      await this.connService.setup()
      this.bindServiceEvent()
    }
    return this.getRecorder()
      .then(() => {
        this.connService.sendStart()
        return Promise.resolve()
      })
  }

  async stop() {
    // this.closeInterval()
    this.log('[stop]')
    try {
      if (this.recognizer) {
        this.connService.sendEndMsg()
        this.connService.socket?.close()
      }
      this.recorder?.stop()
      return Promise.resolve()
    } catch (error: unknown) {
      this.error(error)
      return Promise.reject(error)
    }
  }

  reviewResultText(useDynamic = true) {
    return (
      this.results?.map?.((result) => fitAsrText(result?.voice_text_str)).join('') ||
      (!useDynamic ? '' : this.processText)
    )
  }

  /**
   * @description 建立连接回调
   * @param {*} res
   */
  onSocketOpen(res) {
    //
  }

  /**
   * @description 开始识别的时候
   * @param {*} res
   */
  onRecStart(res) {
    //
  }

  /**
   * @description 识别结果发生变化的时候
   * @param {*} res
   */
  onSentenceChange(res) {
    //
  }

  /**
   * @description 一句话结束的时候
   * @param {*} res
   */
  onSentenceEnd(res) {
    //
  }

  /**
   * @description 识别结束的时候
   * @param {*} res
   */
  onRecComplete(res) {
    //
  }

}
